#pragma once

#include <time.h>
#include <functional>
#include <iostream>

class timer
{
    typedef std::function<void()> call_back_t;
public:
    void set_expire(const time_t &exprie) {_expire = exprie;}
    time_t &use_expire() {return _expire;}
    void set_expire_handler(const call_back_t &cb) {_cb = cb;}
protected:
    time_t _expire;
public:
    timer *_next;
    timer *_prev;
    call_back_t _cb;// 超时之后的回调函数
};


class timer_manager// 本质是一个双向链表
{
public:
    timer_manager()
    {
        while(_head)
        {
            timer *del = _head;
            _head = _head->_next;
            delete del;
            del = nullptr;
        }
    }
    void add(timer *tm)
    {
        //1. 如果要插入的定时器为空
        if(tm == nullptr) return;
        //2. 如果链表本身为空
        if(_head == nullptr)
        {
            _head = tm;
            _tail = tm;
            return ;
        }
        //3. 如果插入的定时器时间小于当前头节点的定时器时间
        if(tm->use_expire() < _head->use_expire())
        {
            tm->_next = _head;
            _head->_prev = tm;
            _head = tm;
            _head->_prev = nullptr;
            return;
        }
        //4. 如果没有小于头节点，那就要从头节点的下一个节点开始插
        timer *cur = _head->_next;
        //4.1 如果为空，则是尾插
        if(cur == nullptr) 
        {
            _tail->_next = tm;
            tm->_prev = _tail;
            _tail = tm;
            return;
        }
        //4.2 开始遍历，直到找到比自己大的节点，然后"头插"
        timer *prev = cur->_prev;// cur节点前面一定有一个头节点
        while(cur)
        {
            if(tm->use_expire() < cur->use_expire())
            {
                prev->_next = tm;
                tm->_prev = prev;
                tm->_next = cur;
                cur->_prev = tm;
                return;
            }
            prev = cur;
            cur = cur->_next;
        }
        //4.3 如果一直未能插入，那么就是尾插
        if(cur == nullptr)
        {
            _tail->_next = tm;
            tm->_prev = _tail;
            _tail = tm;
            return;
        }
    }

    void del(timer *tm)
    {
        //1. 如果要删除的定时器为空
        if(tm == nullptr) return;
        //2. 如果链表当中只有一个节点
        if(tm == _head && tm == _tail)
        {
            delete tm;
            tm = nullptr;
            _head = _tail = nullptr;
            return;
        }
        //3. 如果要删除的节点是头
        if(tm == _head)
        {
            _head = _head->_next;
            _head->_prev = nullptr;
            delete tm;
            tm = nullptr;
            return;
        }
        //4. 如果要删除节点是尾
        if(tm == _tail)
        {
            _tail = _tail->_prev;
            _tail->_next = nullptr;
            delete tm;
            tm = nullptr;
            return;
        }
        //5. 如果删除的是中间节点
        timer *prev = tm->_prev;
        prev->_next = tm->_next;
        tm->_next->_prev = prev;
        delete tm;
        tm = nullptr;
    }

    void adjust(timer *tm)
    {
        //1. 如果要调整的定时器为空
        if(tm == nullptr) return;
        //2. 如果要调整的定时器为头
        if(tm == _head)
        {
            _head = _head->_next;
            _head->_prev = nullptr;
            add(tm);
            return;
        }
        //3. 如果要调整的定时器为尾
        if(tm == _tail)
        {
            _tail = _tail->_next;
            _tail->_next = nullptr;
            add(tm);
        }
        //4. 其他情况
        timer *prev = tm->_prev;
        prev->_next = tm->_next;
        tm->_next->_prev = prev;
        add(tm);
    }

    void tick()
    {
        //1. 如果链表当中没有节点
        if(_head == nullptr) return;
        //2. 获取当前的系统时间
        std::cout << "tick()" << std::endl;
        time_t cur_time = time(nullptr);
        timer *cur = _head;
        while(cur)
        {
            // 如果遍历到第一个时间大于当前时间的定时器，就说明从该定时器往后的所有定时器都没超时
            if(cur->use_expire() > cur_time) break;
            // 这里就是所有超时的定时器
            cur->_cb();
            _head = cur->_next;// 删除定时器实质上就是头删
            if(_head) _head->_prev = nullptr;
            delete cur;
            cur = _head;
        }
    }
protected:
    timer *_head = nullptr;
    timer *_tail = nullptr;
};